package com.weng.cloud.service8881.jdk8;

import com.google.common.collect.Lists;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @Author: weng
 * @Date: 2022/5/8
 * @Description:
 *      怎么说呢？
 *      这个东西比较适合规范对象的构造吧
 *      要贯彻到整个项目中的话,需得要看个人习惯吧,毕竟代码不可能是一个人写完的吧
 *
 * @see <a href="https://blog.csdn.net/qq_40794973/article/details/105182689">java.util.Optional</a>
 * @see <a href="https://blog.csdn.net/u010741112/article/details/123135112">java lambda 表达式的局部变量为什么必须是final修饰？</a>
 */

public class TestOptional {

    private static List<Integer> out;

    public static void main(String[] args) {

        final List<Integer> in = Arrays.asList(1,-6,null,218,23,1,null,-33);

        // 我们需要做到：
        //  如果out不为null -> 每个不为null的元素做一次绝对值运算
        //  如果out为null -> 返回一个size=0的空集合

        dealProblem(in);

        Consumer c = list -> System.err.println(list);

        c.accept(obtainOut());
    }

    private final static void dealProblem(final List<Integer> in){

        Optional
                .ofNullable(in)
                .ifPresent(
                        inTmp -> {
                            // 编译器不允许lambda表达中对线程私有变量赋值
                            // 这虽然不会有安全问题
                            // 这是为了防止语义混乱的考虑
                            out = inTmp
                                    .stream()
                                    .filter(Objects::nonNull)
                                    .map(Math::abs)
                                    .collect(
                                            Collectors.toList()
                                    )
                            ;
                        }
                )
        ;
    }

    private final static List<Integer> obtainOut(){
        return Optional
                .ofNullable(out)
                .orElse(Lists.newArrayList())
        ;
    }

/*
    out >
        {"no":3,"name":"lorry"}
        {"no":3,"name":"lorry"}
    conclusion >
        引用类型的传递的是其实是地址
        实质是创建一个新的局部变量
        并指向作为参数传递到方法的地址

    public static void main(String[] args) {
        Person p = new Person(3,"lorry");
        System.out.println(p);
        testProp(p);
        System.err.println(p);
    }

    private static void testProp(Person p){
        p = Person.builder().name("beal").no(3).build();
    }
*/
}
